package com.my.study.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {

    private static RedisTemplate redisTemplate;


    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate template;

    private RedisUtil() {
    }

    @PostConstruct
    public void getInstance(){
        redisTemplate = template;
    }

    /**
     * 返回是否存在该key
     *
     * @param key key
     * @return 是否存在该key
     */
    public static Boolean existKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 加锁
     *
     * @param key
     * @param value
     * @param timeout
     * @param timeUnit
     * @return
     */
    public static boolean setNx(String key,String value,long timeout,TimeUnit timeUnit){
        return redisTemplate.opsForValue().setIfAbsent(key,value,timeout,timeUnit);
    }

    /**
     * 给某个key设置过期时间
     *
     * @param key  key
     * @param time 过期时间
     * @return 返回是否设置成功
     */
    public static Boolean expire(String key, long time) {
        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * setex
     *
     * @param key   key
     * @param value value
     * @param time  过期时间
     */
    public static Boolean setValueExpire(String key, Object value, long time) {
        Boolean result = existKey(key);
        if (!result) {
            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
        }
        return result;
    }

    /**
     * 批量设置key和value
     *
     * @param map key和value的集合
     */
    public static void multiMapSet(Map<String, Object> map) {
        redisTemplate.opsForValue().multiSet(map);
    }

    /**
     * 如果key不存在，则设置
     *
     * @param key   key
     * @param value value
     * @return 返回是否成功
     */
    public static Boolean setString(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 批量设置hash
     *
     * @param key  key
     * @param map  hashKey和value的集合
     * @param time 过期时间
     * @return 是否成功
     */
    public static Boolean setHashMap(String key, Map<String, Object> map, long time) {
        redisTemplate.opsForHash().putAll(key, map);
        return expire(key, time);
    }

    /**
     * 删除对应key
     *
     * @param key key
     * @return 返回是否删除成功
     */
    public static Boolean del(String key) {
        return redisTemplate.delete(key);
    }

    /**
     * String类型的get
     *
     * @param key key
     * @return 返回value对应的对象
     */
    public static String getSting(String key) {
        return JsonUtil.objectToString(redisTemplate.opsForValue().get(key));
    }

    /**
     * @param key key
     * @return 返回value对应的对象
     */
    public static <T> T getValue(String key, Class<T> valueType) {
        Object object = redisTemplate.opsForValue().get(key);
        if (!Objects.isNull(object)) {
            return JsonUtil.ObjectToTarget(object, valueType);
        }
        return null;
    }

    /**
     * @param key key
     * @return 返回value对应的对象
     */
    public static <T> T getTargetValue(String key, TypeReference<T> valueType) {
        Object object = redisTemplate.opsForValue().get(key);
        if (!Objects.isNull(object)) {
            return JsonUtil.ObjectToEntity(object, valueType);
        }
        return null;
    }
}
